package com.example.yingjiguanli_demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.yingjiguanli_demo.Strategy.user.AuthenticationStrategy;
import com.example.yingjiguanli_demo.Strategy.user.PasswordCorrectStrategy;
import com.example.yingjiguanli_demo.Strategy.user.UserEnabledStrategy;
import com.example.yingjiguanli_demo.Strategy.user.UserExistsStrategy;
import com.example.yingjiguanli_demo.config.SessionManager;
import com.example.yingjiguanli_demo.mapper.UsersMapper;
import com.example.yingjiguanli_demo.pojo.*;
import com.example.yingjiguanli_demo.service.UsersService;
import com.example.yingjiguanli_demo.utils.IpUtils.AddressUtils;
import com.example.yingjiguanli_demo.utils.IpUtils.IpUtil;
import com.example.yingjiguanli_demo.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import static com.example.yingjiguanli_demo.utils.ConstantUtils.USER_SESSION_NAME;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author scj
 * @since 2024-11-04
 */
@Service
@Slf4j
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements UsersService {
    @Autowired
    private SessionManager sessionManager;
    @Resource
    private UsersMapper userMapper;

    @Autowired
    private LoginAsyncService loginAsyncService;

    /***
     * 用户登录
     * @param loginRequest 登录信息
     * @param response http
     * @param request http
     * @return 登录结果
     */
    @Override
    public Result<T> login(LoginRequest loginRequest, HttpServletResponse response, HttpServletRequest request) {

        // 初始化登录日志实体
        LoginLog loginLog = new LoginLog();
        String ip = IpUtil.getIpAddr(request);
        // 从数据库中查找用户
        Users users = userMapper.findByUsername(loginRequest.getUsername());


        // 创建策略列表，将所有策略添加到列表中
        List<AuthenticationStrategy> strategies = new ArrayList<>();
        strategies.add(new UserExistsStrategy());
        strategies.add(new UserEnabledStrategy());
        strategies.add(new PasswordCorrectStrategy());

        // 遍历策略列表，逐个执行策略的认证方法
        for (AuthenticationStrategy strategy : strategies) {
            if (!strategy.authenticate(users, loginRequest)) {
                //在线获取
                String realAddress = AddressUtils.getRealAddressByIP(ip);
                loginLog.setLoginIp(request.getRemoteAddr());
                loginLog.setLoginAddress(realAddress);
                loginLog.setUserId(Math.toIntExact(users.getId())); // 设置用户ID
                loginLog.setLoginTime(new Date()); // 设置登录时间
                loginLog.setLoginResult(strategy.getFailureMessage());
                //保存登录日志
                loginAsyncService.saveLoginLog(loginLog);
                return Result.failed(strategy.getFailureMessage());
            }
        }


        // 生成新的Session ID
        String sessionId = UUID.randomUUID().toString();
        log.info("sessionId: {}", sessionId);
        // 生成JWT Token
        String token = JwtUtils.createToken(users.getUsername());
        log.info("正在为用户 {} 创建新的会话，Session ID: {}, Token: {}", users.getId(), sessionId, token);
        // 将Session ID和JWT Token存储到Redis中，关联用户ID
        sessionManager.createSession(sessionId, token, (long) users.getId());

        // 设置Session ID到Cookie
        Cookie cookie = new Cookie(USER_SESSION_NAME, sessionId);
        cookie.setMaxAge(60 * 60 * 24 * 7);
        cookie.setHttpOnly(true);
        cookie.setPath("/");
        response.addCookie(cookie);
        //在线获取
        String realAddress = AddressUtils.getRealAddressByIP(ip);
        loginLog.setLoginIp(request.getRemoteAddr());
        loginLog.setLoginAddress(realAddress);
        loginLog.setUserId(Math.toIntExact(users.getId())); // 设置用户ID
        loginLog.setLoginTime(new Date()); // 设置登录时间
        loginLog.setLoginResult("登陆成功!");
        //保存登录日志
        loginAsyncService.saveLoginLog(loginLog);
        // 返回成功消息
        return Result.success("登录成功！");
    }

    /***
     * 用户注册
     * @param username 用户名
     * @param password 密码
     * @param email 邮箱
     * @return 注册结果
     */
    @Override
    public Result<T> register(String username, String password, String email) {
        return null;
    }

    /***
     * 用户登出
     * @param request http
     * @param response http
     * @return 登出结果
     */
    @Override
    public Result<T> logout(HttpServletRequest request, HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (USER_SESSION_NAME.equals(cookie.getName())) {
                    // 获取Session ID
                    String sessionId = cookie.getValue();

                    // 使会话无效
                    try {
                        sessionManager.invalidateSession(sessionId);
                        log.info("Session ID {} 已注销", sessionId);
                    } catch (Exception e) {
                        log.error("注销Session ID {} 失败", sessionId, e);
                        return Result.failed("注销失败，请重试");
                    }

                    // 清除Cookie
                    cookie.setValue(null);
                    cookie.setMaxAge(0);
                    cookie.setPath("/"); // 确保删除同路径的Cookie
                    response.addCookie(cookie);


                    break;
                }
            }
        }

        // 返回成功消息
        return Result.success("已成功注销");
    }

    /***
     * 获取所有用户
     * @return 所有用户
     */
    @Override
    public Result<List<UserRoleDTO>> getAllUsers() {
        // 获取所有用户信息，并已处理权限字段
        List<UserRoleDTO> userRoleDTOList = userMapper.getAllUsersWithRoles();
        return Result.success(userRoleDTOList);
    }


    /***
     *  获取用户信息
     * @param id 用户id
     * @return 用户信息
     */
    @Override
    public Result<UserRoleDTO> getUserInfo(Long id) {
        UserRoleDTO user = userMapper.getUserById(id);
        return Result.success(user);
    }


    @Override
    public Result<T> passUser(Long userId) {
        //查询用户是否为警用状态
        Users user = userMapper.selectOne(new QueryWrapper<Users>().eq("id", userId));
        if (user.getStatus() == 1) {
            //解冻用户
            UpdateWrapper<Users> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", userId).set("status", 0);
            userMapper.update(user, updateWrapper);
            return Result.success("解冻成功");
        }
        UpdateWrapper<Users> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", userId).set("status", 1);
        userMapper.update(user, updateWrapper);
        return Result.success("禁用成功");
    }
}
